﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using PSLibrary = Microsoft.Office.Project.Server.Library;

using DataDesign.MPP.Utilities;

namespace DataDesign.MPP.ServerManager
{
    public class ResourceManager
    {
        private static log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public static Guid PPROJECT_ENTITY_GUID = new Guid(PSLibrary.EntityCollection.Entities.ProjectEntity.UniqueId);
        public static Guid RESOURCE_ENTITY_GUID = new Guid(PSLibrary.EntityCollection.Entities.ResourceEntity.UniqueId);
        public static Guid TASK_ENTITY_GUID = new Guid(PSLibrary.EntityCollection.Entities.TaskEntity.UniqueId);

        public enum EntityType
        {
            ProjectEntity,
            ResourceEntity,
            TaskEntity
        }

        public static Guid GetGuidByEntityType(EntityType type)
        {
            if (type == EntityType.ProjectEntity)
                return PPROJECT_ENTITY_GUID;
            if (type == EntityType.ResourceEntity)
                return RESOURCE_ENTITY_GUID;
            if (type == EntityType.TaskEntity)
                return TASK_ENTITY_GUID;

            return Guid.Empty;
        }
        public static WebSvcResource.ResourceDataSet.ResourcesRow GetCurrentUser()
        {
            try
            {
                logger.Debug("BEGIN GetCurrentUser");
                WebSvcResource.Resource ws = HelperServerManager.GetWebSvcResource();
                Guid userGuid = ws.GetCurrentUserUid();
                logger.DebugFormat("Current user guid: {0}", userGuid);

                WebSvcResource.ResourceDataSet userResource = ws.ReadResource(userGuid);

                if (userResource != null)
                {
                    logger.DebugFormat("userResource: {0}", userResource.GetXml());
                    return userResource.Resources[0];
                }
                else
                {
                    logger.Debug("GetCurrentUser is NULL");
                    return null;
                }
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetCurrentUser", ex);
                throw;
            }
        }

        public static WebSvcResource.ResourceDataSet GetAllResourcesOnServer()
        {
            try
            {
                WebSvcResource.ResourceDataSet dsResource = HelperServerManager.GetWebSvcResource().ReadResources(string.Empty, false);
                logger.DebugFormat("Xml of all resources: {0}", dsResource.GetXml());
                return dsResource;
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetAllResourcesOnServer", ex);
                throw;
            }
        }

        public static WebSvcCustomFields.CustomFieldDataSet GetAllCustomFieldsOnServer()
        {
            try
            {
                WebSvcCustomFields.CustomFieldDataSet dsCustomFields = HelperServerManager.GetWebSvcCustomFields().ReadCustomFields(string.Empty, false);
                logger.DebugFormat("Xml of all custom fields: {0}", dsCustomFields.GetXml());
                return dsCustomFields;
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetAllCustomFieldsOnServer", ex);
                throw;
            }
        }

        public static WebSvcLookupTable.LookupTableDataSet GetAllLookupTableOnServer()
        {
            try
            {
                WebSvcLookupTable.LookupTableDataSet dsLookupTable = HelperServerManager.GetWebSvcLookupTable().ReadLookupTables(string.Empty, false, 0);
                logger.DebugFormat("Xml of all lookup tables: {0}", dsLookupTable.GetXml());
                return dsLookupTable;
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetAllLookupTableOnServer", ex);
                throw;
            }
        }

        public static WebSvcCustomFields.CustomFieldDataSet.CustomFieldsRow GetCustomFieldByName(string customFieldName, EntityType entityType)
        {
            try
            {
                logger.DebugFormat("BEGIN GetCustomFieldGuidByName. customFieldName: {0}, entityType: {1}", customFieldName, entityType);

                #region Create Filter
                WebSvcCustomFields.CustomFieldDataSet.CustomFieldsDataTable dtCustomField = new WebSvcCustomFields.CustomFieldDataSet().CustomFields;
                PSLibrary.Filter filter = new PSLibrary.Filter();
                filter.FilterTableName = dtCustomField.TableName;

                HelperServerManager.AddAllFieldsToFilder(filter, dtCustomField.Columns);
                //filter.Fields.Add(new PSLibrary.Filter.Field(dtCustomField.TableName, dtCustomField.MD_PROP_NAMEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.Desc));  
                //filter.Fields.Add(new PSLibrary.Filter.Field(dtCustomField.MD_PROP_UIDColumn.ColumnName));

                //filter.Criteria = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, dtCustomField.MD_ENT_TYPE_UIDColumn.ColumnName, GetGuidByEntityType(entityType));               

                filter.Criteria = new PSLibrary.Filter.LogicalOperator(
                    PSLibrary.Filter.LogicalOperationType.And,
                    new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, dtCustomField.MD_ENT_TYPE_UIDColumn.ColumnName, GetGuidByEntityType(entityType)),
                    new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, dtCustomField.MD_PROP_NAMEColumn.ColumnName, customFieldName)
                );

                logger.DebugFormat("filter: {0}", filter.GetXml());
                #endregion

                WebSvcCustomFields.CustomFieldDataSet dsCustomField = HelperServerManager.GetWebSvcCustomFields().ReadCustomFields(filter.GetXml(), false);
                if (dsCustomField == null || dsCustomField.CustomFields == null)
                    throw new Exception(string.Format("There is no resource {0} of type {1} on Server", customFieldName, entityType));

                logger.DebugFormat("dsCustomField: {0}", dsCustomField.GetXml());
                //return dsCustomField.CustomFields[0].MD_PROP_UID;
                return dsCustomField.CustomFields[0];
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetCustomFieldGuidByName", ex);
                throw;
            }
        }

        public static string GetValueForCustomFieldOfResource(WebSvcResource.ResourceDataSet.ResourcesRow resourceRow, string customFieldName)
        {
            try
            {
                logger.DebugFormat("BEGIN GetValueForCustomFieldOfResource. customFieldName: {0}", customFieldName);
                Guid valueGuid = GetGuidValueForCustomFieldOfResource(resourceRow, customFieldName);
                logger.DebugFormat("valueGuid: {0}", valueGuid);

                if (valueGuid == Guid.Empty)
                {
                    logger.DebugFormat("Resource {0} do not have custom field {1}. Return NULL !", resourceRow.RES_NAME, customFieldName);
                    return null;
                }

                return GetLookupTableTextByGuid(valueGuid);
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetValueForCustomFieldOfResource", ex);
                throw;
            }
            
        }
        public static Guid GetGuidValueForCustomFieldOfResource(WebSvcResource.ResourceDataSet.ResourcesRow resourceRow, string customFieldName)
        {
            try
            {
                logger.DebugFormat("BEGIN GetGuidValueForCustomFieldOfResource. customFieldName: {0}", customFieldName);
                Guid customFieldGuid = GetCustomFieldByName(customFieldName, EntityType.ResourceEntity).MD_PROP_UID;
                logger.DebugFormat("customFieldGuid: {0}", customFieldGuid);

                Guid valueGuid = Guid.Empty;
                foreach (WebSvcResource.ResourceDataSet.ResourceCustomFieldsRow customFieldRow in resourceRow.GetResourceCustomFieldsRows())
                {
                    if (customFieldRow.MD_PROP_UID == customFieldGuid)
                    {
                        valueGuid = customFieldRow.CODE_VALUE;
                        break;
                    }
                }

                logger.DebugFormat("END GetGuidValueForCustomFieldOfResource. valueGuid: {0}", valueGuid);
                return valueGuid;
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetGuidValueForCustomFieldOfResource", ex);
                throw;
            }
        }

        public static string GetLookupTableTextByGuid(Guid lookupTableGuid)
        {
            try
            {
                logger.DebugFormat("BEGIN GetLookupTableTextByGuid. lookupTableGuid: {0}", lookupTableGuid);
                WebSvcLookupTable.LookupTableDataSet dsLookup = GetAllLookupTableOnServer();
                foreach (WebSvcLookupTable.LookupTableDataSet.LookupTableTreesRow treeRow in dsLookup.LookupTableTrees)
                {
                    if (treeRow.LT_STRUCT_UID == lookupTableGuid)
                    {
                        logger.DebugFormat("Text: {0}", treeRow.LT_VALUE_TEXT);
                        return treeRow.LT_VALUE_TEXT;
                    }
                }

                return null;
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetLookupTableTextByGuid", ex);
                throw;
            }
        }

        public static Dictionary<Guid, string> GetLookupTableDictionaryForProjectPriorityLevel()
        {
            try
            {
                logger.Debug("BEGIN GetLookupTableDictionaryForProjectPriorityLevel");
                var dic = GetLookupTableDictionaryForCustomField(ResourceUtil.GetString("NAME_PROJECT_PRIORITY_LEVEL"), EntityType.ProjectEntity);
                var ret = new Dictionary<Guid, string>();
                foreach (WebSvcLookupTable.LookupTableDataSet.LookupTableTreesRow row in dic.Values)
                {
                    //Modify here if change Priority Level lookup table
                    ret.Add(row.LT_STRUCT_UID, row.LT_VALUE_NUM + "-" + row.LT_VALUE_DESC);
                }

                ret.Add(Guid.Empty, null);      // Add default NULL for un-found Guid
                return ret;
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetLookupTableDictionaryForProjectPriorityLevel", ex);
                throw;
            }
        }

        public static Dictionary<Guid, WebSvcLookupTable.LookupTableDataSet.LookupTableTreesRow> GetLookupTableDictionaryForCustomField(string customFieldName, EntityType type)
        {
            try
            {
                logger.DebugFormat("BEGIN GetLookupTableDictionaryForCustomFieldOfResource. customFieldName: {0}", customFieldName);
                Guid guidLookupTableOfResource = GetCustomFieldByName(customFieldName, type).MD_LOOKUP_TABLE_UID;
                logger.DebugFormat("guidLookupTableOfResource: {0}", guidLookupTableOfResource);

                #region Create Filter
                WebSvcLookupTable.LookupTableDataSet.LookupTableTreesDataTable dtLookupTableTrees = new WebSvcLookupTable.LookupTableDataSet.LookupTableTreesDataTable();

                PSLibrary.Filter filter = new PSLibrary.Filter();
                filter.FilterTableName = dtLookupTableTrees.TableName;

                HelperServerManager.AddAllFieldsToFilder(filter, dtLookupTableTrees.Columns);
                //filter.Fields.Add(new PSLibrary.Filter.Field(dtLookupTableTrees.LT_STRUCT_UIDColumn.ColumnName));
                //filter.Fields.Add(new PSLibrary.Filter.Field(dtLookupTableTrees.LT_VALUE_TEXTColumn.ColumnName));

                filter.Criteria = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, dtLookupTableTrees.LT_UIDColumn.ColumnName, guidLookupTableOfResource);

                logger.DebugFormat("filter: {0}", filter.GetXml());
                #endregion

                WebSvcLookupTable.LookupTableDataSet dsLookupTable = HelperServerManager.GetWebSvcLookupTable().ReadLookupTables(filter.GetXml(), false, 0);
                if (dsLookupTable == null || dsLookupTable.LookupTableTrees == null)
                    throw new Exception(string.Format("There is no lookup table for resource {0} on Server", customFieldName));

                logger.DebugFormat("dsLookupTable: {0}", dsLookupTable.GetXml());

                var ret = new Dictionary<Guid, WebSvcLookupTable.LookupTableDataSet.LookupTableTreesRow>();
                foreach (WebSvcLookupTable.LookupTableDataSet.LookupTableTreesRow row in dsLookupTable.LookupTableTrees)
                {
                    //ret.Add(row.LT_STRUCT_UID, row.LT_VALUE_TEXT);
                    ret.Add(row.LT_STRUCT_UID, row);
                }

                return ret;
            }
            catch (Exception ex)
            {
                logger.Error("ERROR GetLookupTableDictionaryForCustomFieldOfResource", ex);
                throw;
            }
        }
    }
}
